#pragma once
#include <iostream>
#include <sys/select.h>
#include "Logger.hpp"
#include "Socket.hpp"

const static int gsize = sizeof(fd_set) * 8;

class TcpSelectServer
{
public:
    TcpSelectServer(uint16_t port) : _listensock(std::make_unique<TcpSocket>())
    {
        _listensock->BuildTcpSocket(port);
        for (int i = 0; i < gsize; i++)
        {
            fd_arry[i] = -1;
        }
        fd_arry[0] = _listensock->SockFd();
    }
    void Accepter()
    {
        InetAddr clientaddr;
        int fd=_listensock->Accept(&clientaddr);
        //将fd添加到fd_arry
        for(int i=0;i<gsize;i++)
        {
            if(fd_arry[i]==-1)
            {
                fd_arry[i]=fd;
            }
        }
        LOG(LogLevel::DEBUG)<<"将文件描述符"<<fd<<"添加到fd_arry";
        
    }
    void Recver()
    {

    }
    void EventDispatch(fd_set&rfd)
    {
        LOG(LogLevel::INFO)<<"有新事件到来,开始派发任务";
        for(int i=0;i<gsize;i++)
        {
            if(fd_arry[i]==-1)
                continue;
            if(FD_ISSET(fd_arry[i],&rfd))
            {
                if(fd_arry[i]==_listensock->SockFd())
                {
                    Accepter();
                }
                else
                {
                    Recver();
                }
            }
        }
    }
    void Run()
    {
        while (true)
        {
            struct timeval timeout = {0, 0};
            fd_set rfd;
            FD_ZERO(&rfd);
            int maxfd = -1;
            for (int i = 0; i < gsize; i++)
            {
                if (fd_arry[i] == maxfd)
                    continue;
                FD_SET(fd_arry[i], &rfd);
                if (maxfd < fd_arry[i])
                {
                    maxfd = fd_arry[i];
                }
                LOG(LogLevel::DEBUG) << "添加fd: " << fd_arry[i];
            }
            int n = select(maxfd, &rfd, nullptr, nullptr, &timeout);
            switch (n)
            {
            case 0:
                LOG(LogLevel::WARNING) << "timeout..." << timeout.tv_sec << " : " << timeout.tv_usec;
                break;
            case -1:
                LOG(LogLevel::ERRO) << "select erro";
                break;
            default:
                EventDispatch(rfd);
                break;
            }
        }
    }
    ~TcpSelectServer() {}

private:
    std::unique_ptr<Socket> _listensock;
    int fd_arry[gsize];
};